home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / doc / sg3-utils / examples / sg_simple2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-03-12  |  6.6 KB  |  197 lines

  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include "sg_linux_inc.h"
  11.  
  12. /* This is a simple program executing a SCSI INQUIRY command and a
  13.    TEST UNIT READY command using the SCSI generic (sg) driver.
  14.    There is another variant of this program called "sg_simple1"
  15.    which includes the sg_lib.h header and logic and so has more
  16.    advanced error processing.
  17.    This version demonstrates the "sg3" interface.
  18.    In the lk 2.6 series devices nodes such as /dev/sda also support
  19.    the SG_IO ioctl.
  20.  
  21. *  Copyright (C) 1999-2007 D. Gilbert
  22. *  This program is free software; you can redistribute it and/or modify
  23. *  it under the terms of the GNU General Public License as published by
  24. *  the Free Software Foundation; either version 2, or (at your option)
  25. *  any later version.
  26.  
  27.    Invocation: sg_simple2 [-x] <scsi_device>
  28.  
  29.    Version 03.58 (20070312)
  30.  
  31. 6 byte INQUIRY command:
  32. [0x12][   |lu][pg cde][res   ][al len][cntrl ]
  33.  
  34. 6 byte TEST UNIT READY command:
  35. [0x00][   |lu][res   ][res   ][res   ][res   ]
  36.  
  37. */
  38.  
  39. #define INQ_REPLY_LEN 96        /* logic assumes >= sizeof(inqCmdBlk) */
  40. #define INQ_CMD_LEN 6
  41. #define TUR_CMD_LEN 6
  42.  
  43. #define EBUFF_SZ 256
  44.  
  45.  
  46. int main(int argc, char * argv[])
  47. {
  48.     int sg_fd, k;
  49.     unsigned char inqCmdBlk [INQ_CMD_LEN] =
  50.                                 {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
  51.     unsigned char turCmdBlk [TUR_CMD_LEN] =
  52.                                 {0x00, 0, 0, 0, 0, 0};
  53.     unsigned char inqBuff[INQ_REPLY_LEN];
  54.     sg_io_hdr_t io_hdr;
  55.     char * file_name = 0;
  56.     char ebuff[EBUFF_SZ];
  57.     unsigned char sense_buffer[32];
  58.     int do_extra = 0;
  59.  
  60.     for (k = 1; k < argc; ++k) {
  61.         if (0 == memcmp("-x", argv[k], 2))
  62.             do_extra = 1;
  63.         else if (*argv[k] == '-') {
  64.             printf("Unrecognized switch: %s\n", argv[k]);
  65.             file_name = 0;
  66.             break;
  67.         }
  68.         else if (0 == file_name)
  69.             file_name = argv[k];
  70.         else {
  71.             printf("too many arguments\n");
  72.             file_name = 0;
  73.             break;
  74.         }
  75.     }
  76.     if (0 == file_name) {
  77.         printf("Usage: 'sg_simple2 [-x] <sg_device>'\n");
  78.         return 1;
  79.     }
  80.     
  81.     /* N.B. An access mode of O_RDWR is required for some SCSI commands */
  82.     if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
  83.         snprintf(ebuff, EBUFF_SZ,
  84.          "sg_simple2: error opening file: %s", file_name);
  85.         perror(ebuff);
  86.         return 1;
  87.     }
  88.     /* Just to be safe, check we have a new sg device by trying an ioctl */
  89.     if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
  90.         printf("sg_simple2: %s doesn't seem to be an new sg device\n", 
  91.                file_name);
  92.         close(sg_fd);
  93.         return 1;
  94.     }
  95.     
  96.     /* Prepare INQUIRY command */
  97.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  98.     io_hdr.interface_id = 'S';
  99.     io_hdr.cmd_len = sizeof(inqCmdBlk);
  100.     /* io_hdr.iovec_count = 0; */  /* memset takes care of this */
  101.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  102.     io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  103.     io_hdr.dxfer_len = INQ_REPLY_LEN;
  104.     io_hdr.dxferp = inqBuff;
  105.     io_hdr.cmdp = inqCmdBlk;
  106.     io_hdr.sbp = sense_buffer;
  107.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  108.     /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
  109.     /* io_hdr.pack_id = 0; */
  110.     /* io_hdr.usr_ptr = NULL; */
  111.  
  112.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  113.         perror("sg_simple2: Inquiry SG_IO ioctl error");
  114.         close(sg_fd);
  115.         return 1;
  116.     }
  117.  
  118.     /* now for the error processing */
  119.     if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
  120.         if (io_hdr.sb_len_wr > 0) {
  121.             printf("INQUIRY sense data: ");
  122.             for (k = 0; k < io_hdr.sb_len_wr; ++k) {
  123.                 if ((k > 0) && (0 == (k % 10)))
  124.                     printf("\n  ");
  125.                 printf("0x%02x ", sense_buffer[k]);
  126.             }
  127.             printf("\n");
  128.         }
  129.         if (io_hdr.masked_status)
  130.             printf("INQUIRY SCSI status=0x%x\n", io_hdr.status);
  131.         if (io_hdr.host_status)
  132.             printf("INQUIRY host_status=0x%x\n", io_hdr.host_status);
  133.         if (io_hdr.driver_status)
  134.             printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status);
  135.     }
  136.     else {  /* output result if it is available */
  137.         char * p = (char *)inqBuff;
  138.         int f = (int)*(p + 7);
  139.         printf("Some of the INQUIRY command's results:\n");
  140.         printf("    %.8s  %.16s  %.4s  ", p + 8, p + 16, p + 32);
  141.         printf("[wide=%d sync=%d cmdque=%d sftre=%d]\n",
  142.                !!(f & 0x20), !!(f & 0x10), !!(f & 2), !!(f & 1));
  143.     }
  144.     /* Extra info, not necessary to look at */
  145.     if (do_extra)
  146.         printf("INQUIRY duration=%u millisecs, resid=%d, msg_status=%d\n",
  147.                io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
  148.     
  149.     /* Prepare TEST UNIT READY command */
  150.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  151.     io_hdr.interface_id = 'S';
  152.     io_hdr.cmd_len = sizeof(turCmdBlk);
  153.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  154.     io_hdr.dxfer_direction = SG_DXFER_NONE;
  155.     io_hdr.cmdp = turCmdBlk;
  156.     io_hdr.sbp = sense_buffer;
  157.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  158.  
  159.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  160.         perror("sg_simple2: Test Unit Ready SG_IO ioctl error");
  161.         close(sg_fd);
  162.         return 1;
  163.     }
  164.  
  165.     /* now for the error processing */
  166.     if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
  167.         if (io_hdr.sb_len_wr > 0) {
  168.             printf("TEST UNIT READY sense data: ");
  169.             for (k = 0; k < io_hdr.sb_len_wr; ++k) {
  170.                 if ((k > 0) && (0 == (k % 10)))
  171.                     printf("\n  ");
  172.                 printf("0x%02x ", sense_buffer[k]);
  173.             }
  174.             printf("\n");
  175.         }
  176.         else if (io_hdr.masked_status)
  177.             printf("TEST UNIT READY SCSI status=0x%x\n", io_hdr.status);
  178.         else if (io_hdr.host_status)
  179.             printf("TEST UNIT READY host_status=0x%x\n", io_hdr.host_status);
  180.         else if (io_hdr.driver_status)
  181.             printf("TEST UNIT READY driver_status=0x%x\n", 
  182.                    io_hdr.driver_status);
  183.         else
  184.             printf("TEST UNIT READY unexpected error\n");
  185.         printf("Test Unit Ready failed so unit may _not_ be ready!\n");
  186.     }
  187.     else
  188.         printf("Test Unit Ready successful so unit is ready!\n");
  189.     /* Extra info, not necessary to look at */
  190.     if (do_extra)
  191.         printf("TEST UNIT READY duration=%u millisecs, resid=%d, msg_status=%d\n",
  192.                io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
  193.  
  194.     close(sg_fd);
  195.     return 0;
  196. }
  197.